﻿using DapperExtensions;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using System.Data.Common;
using System.Linq;
using static Dapper.SqlMapper;
using Chaunce.FrameWork.NetCore.DapperCore;

namespace Chaunce.Dapper.Repositories
{
    public class DapperRepositoryBase<TEntity, TPrimaryKey> : DapperQueryRepository, IDapperRepository<TEntity, TPrimaryKey> where TEntity : class
    {

        public DapperRepositoryBase(IContext context) : base(context)
        {
        }

        /// <summary>
        /// 获取一个实体对象
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public TEntity Get(TPrimaryKey id)
        {
            return Connection.Get<TEntity>(id, transaction: ActiveTransaction);
            //return Get(CreateEqualityExpressionForId(id));
        }

        public TEntity Get(Expression<Func<TEntity, bool>> predicate)
        {
            IPredicate pg = DapperQueryFilterExecuter.ExecuteFilter<TEntity, TPrimaryKey>(predicate);
            return Connection.GetList<TEntity>(pg, transaction: ActiveTransaction).FirstOrDefault();
        }

        public Task<TEntity> GetAsync(TPrimaryKey id)
        {
            return Task.FromResult(Get(id));
        }

        public Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> predicate)
        {
            return Task.FromResult(Get(predicate));
        }

        /// <summary>
        /// 插入实体
        /// </summary>
        /// <param name="entity"></param>
        public void Insert(TEntity entity)
        {
            InsertAndGetId(entity);
        }

        public TPrimaryKey InsertAndGetId(TEntity entity)
        {
            TPrimaryKey primaryKey = Connection.Insert(entity, ActiveTransaction);
            return primaryKey;
        }

        public Task<TPrimaryKey> InsertAndGetIdAsync(TEntity entity)
        {
            return Task.FromResult(InsertAndGetId(entity));
        }

        public Task InsertAsync(TEntity entity)
        {
            Insert(entity);
            return Task.FromResult(0);
        }

        /// <summary>
        /// 插入实体
        /// </summary>
        /// <param name="entity"></param>
        public int Insert<T>(string tableName, string fields, T entity)
        {
            string[] res = fields.Split(',');
            for (int i = 0; i < res.Length; i++)
            {
                res[i] = "@" + res[i].Trim();
            }
            string sqlText = string.Format(" INSERT INTO {0} ({1}) VALUES ({2}); ", tableName, fields, string.Join(",", res));

            return Connection.Execute(sqlText, entity);

        }

        /// <summary>
        /// 批量插入数据，返回成功的条数（未启用事物）
        /// </summary>
        /// <typeparam name="TEntity">数据库表对应的实体类型</typeparam>
        /// <param name="tableName">数据库表名</param>
        /// <param name="fields">数据库表的所有字段，用【,】分隔（主键自增时应排除主键字段）</param>
        /// <param name="list">数据库表对应的实体集合</param>
        /// <returns>成功的条数</returns>
        public int InsertBulk<T>(string tableName, string fields, List<T> list)
        {
            string[] res = fields.Split(',');
            for (int i = 0; i < res.Length; i++)
            {
                res[i] = "@" + res[i].Trim();
            }
            string sqlText = string.Format(" INSERT INTO {0} ({1}) VALUES ({2}); ", tableName, fields, string.Join(",", res));

            return Connection.Execute(sqlText, list);

        }

        /// <summary>
        /// 更新实体
        /// </summary>
        /// <param name="entity"></param>
        public void Update(TEntity entity)
        {
            Connection.Update(entity, ActiveTransaction);
        }

        public Task UpdateAsync(TEntity entity)
        {
            Connection.Update(entity, ActiveTransaction);
            return Task.FromResult(0);
        }

        /// <summary>
        /// 根据主键，更新唯一的一条记录
        /// </summary>
        /// <param name="connection">sql链接</param>
        /// <param name="primaryKeyName">主键字段名</param>
        /// <param name="primaryKeyValue">主键字段值</param>
        /// <param name="tableName">数据库表名</param>
        /// <param name="dicUpdate">需要更新的字段名/字段值组成的键值对</param>
        /// <returns>更新成功的记录条数</returns>
        public int Update(string primaryKeyName, object primaryKeyValue, string tableName, Dictionary<string, object> dicUpdate)
        {
            if (dicUpdate == null || dicUpdate.Count == 0)
                return 0;
            StringBuilder sqlText = new StringBuilder();
            sqlText.AppendFormat(" UPDATE {0} SET ", tableName);
            DynamicParameters pars = new DynamicParameters();
            string[] fields = new string[dicUpdate.Count];
            int index = 0;
            foreach (string name in dicUpdate.Keys)
            {
                sqlText.AppendFormat(" {0}=@p_{1},", name, index);
                pars.Add("@p_" + index.ToString(), dicUpdate[name]);
                index++;
            }
            sqlText.Remove(sqlText.Length - 1, 1);
            sqlText.AppendFormat(" WHERE {0}=@p_{1} ", primaryKeyName, index.ToString());
            pars.Add("@p_" + index.ToString(), primaryKeyValue);

            return Connection.Execute(sqlText.ToString(), pars);

        }

        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="entity"></param>
        public void Delete(TEntity entity)
        {
            Connection.Delete(entity, ActiveTransaction);

        }

        public void Delete(Expression<Func<TEntity, bool>> predicate)
        {
            IPredicate pg = DapperQueryFilterExecuter.ExecuteFilter<TEntity, TPrimaryKey>(predicate);
            Connection.Delete(pg, ActiveTransaction);

        }

        public Task DeleteAsync(TEntity entity)
        {
            Delete(entity);
            return Task.FromResult(0);
        }

        public Task DeleteAsync(Expression<Func<TEntity, bool>> predicate)
        {
            Delete(predicate);
            return Task.FromResult(0);
        }

        public int Count(Expression<Func<TEntity, bool>> predicate)
        {
            IPredicate filteredPredicate = DapperQueryFilterExecuter.ExecuteFilter<TEntity, TPrimaryKey>(predicate);
            return Connection.Count<TEntity>(filteredPredicate, ActiveTransaction);
        }

        public Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate)
        {
            return Task.FromResult(Count(predicate));
        }

        #region list
        public IList<TEntity> GetList()
        {
            return Connection.GetList<TEntity>(null, transaction: ActiveTransaction).ToList();
        }

        public IList<TEntity> GetList(Expression<Func<TEntity, bool>> predicate)
        {
            IPredicate filteredPredicate = DapperQueryFilterExecuter.ExecuteFilter<TEntity, TPrimaryKey>(predicate);
            return Connection.GetList<TEntity>(filteredPredicate, transaction: ActiveTransaction).ToList();
        }

        public Task<IList<TEntity>> GetListAsync()
        {
            return Task.FromResult(GetList());
        }

        public Task<IList<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate)
        {
            return Task.FromResult(GetList(predicate));
        }
        #endregion

        #region sql语句查询


        public IList<TEntity> Query(string query, object parameters = null)
        {
            return Connection.Query<TEntity>(query, parameters, ActiveTransaction).ToList();
        }

        public async Task<IList<TEntity>> QueryAsync(string query, object parameters = null)
        {
            var data = await Connection.QueryAsync<TEntity>(query, parameters, ActiveTransaction);
            return data.ToList();
        }

        #endregion
    }
}